/*
 * @Author         : mli
 * @Email          : mli@poptown.io
 * @Description    : 
 * @FilePath: /lib/ui/text_input.dart
 * @Date           : 2023-11-14 18:26:32
 * @LastEditTime: 2024-04-10 17:26:56
 * @LastEditors: mli@poptown.io
 */

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gameplay_flutter/lib_baseview/theme/jr.dart';
import 'package:gameplay_flutter/lib_runtime/extension/string_extension/string_validate.dart';
import 'package:gameplay_flutter/lib_runtime/extension/widget/widget_wrapper.dart';
import 'package:gameplay_flutter/lib_runtime/logger.dart';
import 'package:get/get.dart';

import '../../../lib_runtime/extension/string_extension/string_text.dart';

/// 输入框
/// 包含字数
/// 整体被方框包裹
/// 随着输入行数增加
/// 整体高度动态增加
/// 原始的TextField带有字数
/// 可以实现UI效果
/// 但是无法满足对应非ascii字符计数为2个的要求
// ignore: must_be_immutable
class JRInputTextField extends StatelessWidget {
  final String? debugName;

  /// 字数限制
  final int maxLength;

  /// 字数限制
  /// true:用户复制字符超过 maxLength,小于maxLength的字符的长度将放入输入框中
  /// false:用户复制字符超过 maxLength,输入的字符不会放入输入框中
  final bool? copyLengthLimited;

  /// 字数限制提示
  final String? maxLengthTip;

  /// 文字颜色
  /// 默认CC.e5e5e5
  final Color? textColor;

  /// 输入文字字体大小
  /// 默认16
  final double? fontSize;

  /// 字体
  /// 默认OpenSans
  final TextFontFamily? fontFamily;

  /// 提示文字
  final String? hintText;

  /// 提示文字颜色
  final Color? hintTextColor;

  /// 最大行数
  /// 整个输入框自动增加高度的最大高度
  /// 而不是文字的输入行数
  final int? maxLines;

  /// 背景色
  final Color? bgColor;

  /// 文字内容到边框的填充
  final EdgeInsetsGeometry? padding;

  /// 边框圆角
  final double borderRadius;

  /// 边框
  final Color? borderColor;
  final double? borderWidth;

  /// 整体最小高度
  final double minHeight;

  final double maxHeight;

  /// 整体最大高度
  /// !!!: 这里设置无效
  /// 这里设置了会导致输入框的高度固定为maxHeight
  /// maxlines可以实现动态高度的效果
  // final double maxHeight;

  /// 整体宽度
  final double width;

  /// 是否显示计数器
  /// 默认显示
  final bool showCounter;
  final Color? counterColor;

  /// 计数器的字体大小
  final double? counterFontSize;

  /// 计数器的右侧填充
  final double? counterPaddingRight;

  /// 计数器的底部填充
  final double? counterPaddingBottom;

  /// 初始内容
  final String? initialText;

  /// 文字回调流
  final Rx<String?>? text;

  final bool readOnly;

  TextEditingController? controller;
  // final _controller = TextEditingController();
  final _count = 0.obs;

  FocusNode? focusNode;
  void Function(String)? onSubmitted;
  VoidCallback? onEditingComplete;

  /// 文本对齐方式
  final TextAlign? textAlign;

  JRInputTextField({
    super.key,
    required this.maxLength,
    required this.minHeight,
    required this.width,
    this.debugName,
    this.initialText,
    this.text,
    this.maxLengthTip,
    this.textColor,
    this.fontSize,
    this.fontFamily,
    this.hintText,
    this.hintTextColor,
    this.maxLines,
    this.bgColor = Colors.transparent,
    this.padding,
    this.borderRadius = 0,
    this.borderColor = Colors.transparent,
    this.borderWidth,
    this.maxHeight = double.infinity,
    this.showCounter = true,
    this.counterColor,
    this.counterFontSize,
    this.controller,
    this.readOnly = false,
    this.focusNode,
    this.onSubmitted,
    this.onEditingComplete,
    this.counterPaddingBottom,
    this.counterPaddingRight,
    this.textAlign,
    this.copyLengthLimited = false,
  }) {
    focusNode ??= FocusNode();

    final aInitialText = (initialText ?? text?.value)?.trim();

    if (controller == null) {
      controller = TextEditingController(text: aInitialText);
    } else if (aInitialText != null) {
      controller!.text = aInitialText;
    }
    _count.value = aInitialText?.calcLength() ?? 0;

    RLog.i('[text input: $debugName] $hashCode add listener');
    controller?.addListener(() {
      RLog.i(
          '[text input: $debugName] $hashCode on text changed ${controller?.text}');
      final trimmed = controller?.text.trim();
      _count.value = trimmed?.calcLength() ?? 0;
      text?.value = trimmed;
    });
  }

  // @override
  // State<StatefulWidget> createState() => _TextInputState();

  @override
  Widget build(BuildContext context) {
    Widget ret = TextField(
      textAlign: textAlign ?? TextAlign.start,
      inputFormatters: [
        if (copyLengthLimited ?? false)
          LengthLimitingTextInputFormatter(maxLength),
        TextInputFormatter.withFunction((oldValue, newValue) {
          /// 超出了限制的情况下
          /// 允许减少内容
          final oldLen = oldValue.text.calcLength();
          final newLen = newValue.text.calcLength();
          if (newLen > oldLen && newLen > maxLength) {
            // maxLengthTip?.toast();
            return oldValue;
          }
          return newValue;
        })
      ],
      focusNode: focusNode,
      controller: controller,
      // maxLength: maxLength,
      style: TextStyle(
        color: textColor ?? Color(0xFFFFFFFF),
        fontSize: fontSize ?? 16.sp,
        fontFamily: (fontFamily ?? TextFontFamily.harmonyOS).family,
        height: 20.0 / 15,
      ),
      cursorColor: JR.color.cursorColor,
      cursorWidth: 2.w,
      decoration: InputDecoration(
        hintText: hintText,
        hintStyle: TextStyle(
          color: hintTextColor ?? Color(0xFFA397DE),
          fontSize: fontSize ?? 14.sp,
          fontWeight: FontWeight.normal,
          fontFamily: (fontFamily ?? TextFontFamily.harmonyOS).family,
        ),
        // !!!: 这里设置null无效
        hintMaxLines: 10,
        border: InputBorder.none,
        // 无法满足对应非ascii字符计数为2个的要求
        counterText: '',
        // 下面2个设置，保证边框距离为0
        contentPadding: EdgeInsets.zero,
        isCollapsed: true,
      ),
      maxLines: maxLines,
      minLines: 1,
      readOnly: readOnly,
      onEditingComplete: onEditingComplete,
      onSubmitted: onSubmitted,
    );

    /// 添加边框
    if (borderColor != null && borderWidth != null) {
      ret = ret
          .border(
            borderColor: borderColor!,
            borderWidth: borderWidth!,
            bgColor: bgColor,

            /// 在计数器存在的情况下
            /// 底部添加额外的padding
            /// 以避免覆盖计数器
            /// 这里写死了高度为30
            padding: showCounter
                ? padding?.add(EdgeInsets.only(bottom: 30.w))
                : padding,
            alignment: AlignmentDirectional.topStart,
            borderRadius: borderRadius,
          )
          .constrained(BoxConstraints(
            minHeight: minHeight,
            maxHeight: maxHeight,
            minWidth: width,
            maxWidth: width,
          ));
    } else {
      /// 否则添加背景色
      ret = ret
          .colorBg(
            bgColor: bgColor,

            /// 在计数器存在的情况下
            /// 底部添加额外的padding
            /// 以避免覆盖计数器
            /// 这里写死了高度为30
            padding: showCounter
                ? padding?.add(EdgeInsets.only(bottom: 30.w))
                : padding,
            alignment: AlignmentDirectional.topStart,
            borderRadius: borderRadius,
          )
          .constrained(BoxConstraints(
            minHeight: minHeight,
            maxHeight: maxHeight,
            minWidth: width,
            maxWidth: width,
          ));
    }

    /// 添加计数
    if (showCounter) {
      ret = Stack(
        children: [
          ret,
          Obx(() => '${_count.value}/$maxLength'
              .text(
                  color: (counterColor ?? Colors.red),
                  fontSize: counterFontSize ?? fontSize ?? 14.sp,
                  family: TextFontFamily.harmonyOS)
              .positioned(
                  end: counterPaddingRight ?? (padding as EdgeInsets?)?.right,
                  bottom: counterPaddingBottom ??
                      (padding as EdgeInsets?)?.bottom)),
        ],
      );
    }

    /// 在只读模式下，如果需要响应点击
    /// 需要额外的覆盖一层
    /// 否则TextField会‘吃掉’点击事件
    if (readOnly) {
      ret = Stack(
        children: [
          ret,
          SizedBox(
            width: width,
            height: minHeight,
          ).colorBg(bgColor: Colors.transparent),
        ],
      );
      return ret;
    } else {
      return ret.onTap(() => FocusScope.of(context).requestFocus(focusNode));
    }
  }
}
